package slave;

import java.io.*;
import java.net.*;

import commonUtility.LineUtility;
import commonUtility.XmlHandler;


/**
 * @author erond
 * Classe thread che avvia un server multicast per la pubblicazione del file di stato xml interno al gateway
 */
public class MulticastServer extends Thread {

	//File da dove leggo, nella directory dove viene lanciato il server */
	private String FILE = "./xml/gatewayCopy.xml";

	private static BufferedReader in = null;
	private static boolean moreLines = true;
	private ByteArrayOutputStream boStream = null;
	private DataOutputStream doStream = null;
	private MulticastSocket socket = null;
	private DatagramPacket packet = null;
	private byte[] data = null;
	private int numero_linee=0;

	private long WAIT = 10;
	private int port = -1;
	private int time = 0;
	private boolean loop = true;
	static boolean file_test = false;
	// Indirizzo del gruppo multicast e porta
	static InetAddress group = null;
	private commonUtility.XmlHandler xmlHandler = null;


	static MulticastServer prova = null;

	/**
	 * @param gatewayMulticast Indirizzo multicast del gateway sul quale pubblicare l'xml
	 * @param gatewayPort porta sulla quale pubblicare l'xml
	 * @param time imposta una periodicità nella pubblicazione dell'xml sul multicast.
	 * @param loop booleano per impostare la pubblicazione in loop, oppure una volta soltanto
	 * @param xmlHandler riferimento all'oggetto per la manipolazione e gestione sincronizzata dei file xml
	 */
	public MulticastServer(InetAddress gatewayMulticast, int gatewayPort, int time, boolean loop, XmlHandler xmlHandler) {
		group = gatewayMulticast;
		port = gatewayPort;
		this.time = time;
		this.loop = loop;
		this.xmlHandler=xmlHandler;
	}

	/**
	 * @param gatewayMulticast Indirizzo multicast del gateway sul quale pubblicare l'xml
	 * @param gatewayPort porta sulla quale pubblicare l'xml
	 * @param time imposta una periodicità nella pubblicazione dell'xml sul multicast.
	 * @param loop booleano per impostare la pubblicazione in loop, oppure una volta soltanto
	 * @param xmlHandler riferimento all'oggetto per la manipolazione e gestione sincronizzata dei file xml
	 * @param nomeFile Path completo del file da pubblicare
	 */
	public MulticastServer(InetAddress gatewayMulticast, int gatewayPort, int time, boolean loop, XmlHandler xmlHandler, String nomeFile) {
		group = gatewayMulticast;
		port = gatewayPort;
		this.time = time;
		this.loop = loop;
		this.xmlHandler=xmlHandler;
		this.FILE=nomeFile;
	}

	
	/**
	 * Set the loop to "state"
	 * @param state
	 */
	public void setLoop(boolean state) {
		this.loop=state;
	}

	public void run() {

		// Creazione datagram packet e socket
		data = new byte[256];
		packet = new DatagramPacket(data, data.length, group, port);
		try {
			socket = new MulticastSocket(port);
			socket.joinGroup(group);
			System.out.println("Socket: " + socket);
		} catch (Exception e) { }

		boolean start=true;

		while (start)
		{ 

			/**
			 * Creo una copia passiva del file gateway.xml
			 */
			if (xmlHandler!=null) xmlHandler.changeStatusClientXml("copy",null);

			if (loop==false) break;
			numero_linee=LineUtility.linesNumber(FILE);
			if (numero_linee<0) break; 
			moreLines = true; // resetto indicatore linee
			try { 
				// costruisco un nuovo buffered reader
				in = new BufferedReader(new FileReader(FILE));
			} catch (Exception e) {
				System.err.println("Errore nell'apertura del file xml per il MulticastServer\n"+e.getMessage());
				continue;
			}
			try
			{   
				String tmp="LINEE:"+numero_linee;
				boStream = new ByteArrayOutputStream();
				doStream = new DataOutputStream(boStream);
				doStream.writeUTF(tmp);
				data = boStream.toByteArray();
				packet.setData(data);
				socket.send(packet);
				try {
					Thread.sleep( WAIT );
				} catch (Exception e) {continue;}
			} catch (Exception e) {
				System.err.println("Errore nella scrittura su MulticastSocket\n"+e.getMessage());
				continue;
			}

			while (moreLines) {
				//estrazione della linea
				String linea = LineUtility.getNextLine(in);
				if ((linea.equals("Nessuna linea disponibile"))||(linea.isEmpty())) { 
					moreLines = false;
					break; //esco dal ciclo
				}
				try
				{ 
					boStream = new ByteArrayOutputStream();
					doStream = new DataOutputStream(boStream);
					doStream.writeUTF(linea);
					data = boStream.toByteArray();
					packet.setData(data);
					socket.send(packet);
					try {Thread.sleep( WAIT );} catch (Exception e) { continue; }

				} catch (Exception e) {
					System.err.println("Errore nella scrittura su MulticastSocket\n"+e.getMessage());
					continue;
				}
			}//fine while(moreLines)

			/**
			 * controllo che il parametro del costruttore della classe per il loop sia falso.
			 * Se false allora il loop non deve avvenire. Se true faccio una sleep della durata
			 * impostata nel costruttore della classe.
			 */
			if (loop==false) {
				start=false;
			}
			else {try {Thread.sleep( time );} catch (Exception e) { continue; }}

			/**
			 * Chiudo il file aperto
			 */
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}//fine while(start)


	}//fine run()


	/**
	 * Main per prove
	 * @param args
	 */
	public static void main(String args[]) {
		try {
			prova = new MulticastServer(InetAddress.getByName("230.0.0.2"), 65431, 1500, true, null, "./xml/after_gateway.xml");
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

		prova.start();
		try {
			prova.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}//fine MulticastServer
